#ifndef SOULLANG_ARG_PARSE_HPP
#define SOULLANG_ARG_PARSE_HPP


#include <string> 
#include <vector>
#include <map>
#include <memory>


#include "errors.hpp"


namespace arg {
	typedef enum {
		NONE_PARAM_ARG,
		BOOL_PARAM_ARG,
		STR_PARAM_ARG
	} ArgumentType;


	class NoneParamArgument {
	private:
		ArgumentType _type;
		std::string _name;

		bool _isSet;
		bool _isRequired;

		std::string _help;

	public:	
		NoneParamArgument(bool isRequired, std::string name);
		NoneParamArgument(bool isRequired, std::string name, std::string help);

		virtual NoneParamArgument& getInstance();

		ArgumentType getType();
		void setType(ArgumentType type);

		std::string getName();

		bool isSet();
		void set();

		bool isRequired();

		std::string getHelp();
		void setHelp(std::string help);
	};

	
	class BoolArgument : public NoneParamArgument {
	private:
		std::string _truePhrase;
		std::string _falsePhrase;

		bool _boolValue;

	public:
		BoolArgument(bool isRequired, std::string name, std::string truePhrase, std::string falsePhrase);	
		BoolArgument(bool isRequired, std::string name, std::string truePhrase, std::string falsePhrase, std::string help);

		bool getBoolValue();
		void setBoolValue(std::string value);
	};

	
	class StringArgument : public NoneParamArgument {
	private:
		std::string _text;
	
	public:
		StringArgument(bool isRequired, std::string name);
		StringArgument(bool isRequired, std::string name, std::string help);

		std::string getText();
		void setText(std::string text);
	};


	class ArgParser {
	private:
		std::map<std::string, std::shared_ptr<NoneParamArgument>> _arguments;


		std::vector<std::string> getRequiredArguments();

	public:
		void addNoneParamArgument(bool isRequired, std::string name);
		void addBoolArgument(bool isRequired, std::string name, std::string truePhrase, std::string falsePhrase);
		void addStringArgument(bool isRequired, std::string name);

		void parse(int argc, char *argv[]);

		std::shared_ptr<NoneParamArgument> getArgument(std::string name);
	};

}

#endif
